package com.niiwoo.civet.mobile.controller.thirdPlateform;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.mobile.controller.thirdPlateform.LoginResult.LoginToken;
import com.niiwoo.civet.mobile.shiro.MobileUserDetailException;
import com.niiwoo.civet.mobile.util.ParameterValidator;
import com.niiwoo.civet.mobile.vo.request.user.LoginRequestVO;
import com.niiwoo.civet.trade.dto.request.thirdplateformdata.DataReportChinaJrbRequestDTO;
import com.niiwoo.civet.trade.dto.request.thirdplateformdata.DataReportJrbRequestDTO;
import com.niiwoo.civet.trade.dto.request.thirdplateformdata.WangDaiTianYanRequestDTO;
import com.niiwoo.civet.trade.dto.request.thirdplateformdata.WangDaiZhiJiaRequestDTO;
import com.niiwoo.civet.trade.dto.response.thirdplateformdata.WangDaiTianYanResponseDTO;
import com.niiwoo.civet.trade.dto.response.thirdplateformdata.WangDaiZhiJiaOverDebtResponseDTO;
import com.niiwoo.civet.trade.dto.response.thirdplateformdata.WangDaiZhiJiaProjectResponseDTO;
import com.niiwoo.civet.trade.enums.TradeConfigEnum;
import com.niiwoo.civet.trade.service.configure.TradeConfigDubboService;
import com.niiwoo.civet.trade.service.statisticsinfo.StatisticsInfoDubboService;
import com.niiwoo.civet.user.constants.LoginAccountErrorCode;
import com.niiwoo.tripod.base.utils.DateUtils;
import com.niiwoo.tripod.consumer.helper.Exceptions;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.enums.DeviceTypeEnum;
import com.niiwoo.tripod.web.shiro.UsernamePasswordDeviceToken;
import com.niiwoo.tripod.web.util.RequestUtil;
import com.niiwoo.tripod.web.vo.Empty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;


/**
 * Created by bincun on 2018/8/31.
 */
@RestController
@RequestMapping("/thirdPlateform")
@Api(tags = "第三方数据对接，如网贷之家", description = "/thirdPlateform")
@Slf4j
public class ThirdPlatefromController {
    @Reference(version = "1.0.0")
    private StatisticsInfoDubboService statisticsInfoDubboService;

    @Reference(version = "1.0.0")
    private TradeConfigDubboService tradeConfigDubboService;

    @RequestMapping(value = "/getProjectsByDateForWdzj", method = {RequestMethod.GET})
    @ApiOperation("网贷之家-查询标的信息")
    public WangDaiZhiJiaProjectResponseDTO getProjectsByDateForWdzj(String date,Integer page,Integer pageSize){
        WangDaiZhiJiaProjectResponseDTO responseDTO;
        try {
            Assert.notNull(page,"参数误错");
            Assert.notNull(pageSize,"参数误错");
            Date queryDate = DateUtils.parseDateFromString(date,DateUtils.SHOW_DATE_FORMAT);
            Assert.notNull(queryDate,"参数误错");

            String openFlag = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.WDZJ_OPEN_FLAG);
            Assert.isTrue("1".equals(openFlag),"网贷之家数据未开放");

            WangDaiZhiJiaRequestDTO dto = new WangDaiZhiJiaRequestDTO();
            dto.setPageSize(pageSize);
            dto.setDate(queryDate);
            dto.setCurrentPage(page);
            responseDTO = statisticsInfoDubboService.getProjectsByDateForWdzj(dto);
        }catch (Exception e){
            log.error("网贷之家查询标的信息数据异常",e);
            responseDTO = new WangDaiZhiJiaProjectResponseDTO();
            responseDTO.setBorrowList(Collections.emptyList());
            responseDTO.setTotalPage(1);
            responseDTO.setCurrentPage(1);
            responseDTO.setTotalAmount(0.0);
            responseDTO.setTotalCount(0);
            return responseDTO;
        }
        return responseDTO;
    }

    @RequestMapping(value = "/getOverdebtProjectsWdzj", method = {RequestMethod.GET})
    @ApiOperation("网贷之家-查询提前结清标的信息")
    public WangDaiZhiJiaOverDebtResponseDTO getOverdebtProjectsWdzj(String date, Integer page, Integer pageSize){
        WangDaiZhiJiaOverDebtResponseDTO responseDTO = null;
        try {
            Assert.notNull(page,"参数误错");
            Assert.notNull(pageSize,"参数误错");
            Date queryDate = DateUtils.parseDateFromString(date,DateUtils.SHOW_DATE_FORMAT);
            Assert.notNull(queryDate,"参数误错");
            String openFlag = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.WDZJ_OPEN_FLAG);
            Assert.isTrue("1".equals(openFlag),"网贷之家数据未开放");

            WangDaiZhiJiaRequestDTO dto = new WangDaiZhiJiaRequestDTO();
            dto.setPageSize(pageSize);
            dto.setDate(queryDate);
            dto.setCurrentPage(page);
            responseDTO = statisticsInfoDubboService.getOverdebtProjectsWdzj(dto);
        }catch (Exception e){
            log.error("网贷之家提前结清数据异常",e);
            responseDTO = new WangDaiZhiJiaOverDebtResponseDTO();
            responseDTO.setPreapys(Collections.emptyList());
            responseDTO.setTotalPage(1);
            responseDTO.setCurrentPage(1);
            return responseDTO;
        }
        return responseDTO;
    }

    @RequestMapping(value = "/login", method = {RequestMethod.POST,RequestMethod.GET})
    @ApiOperation("网贷天眼、网贷之家-登录")
    @AuthIgnore
    public LoginResult<LoginToken> login(HttpServletRequest httpServletRequest, String username, String password) throws Throwable {
        LoginRequestVO loginRequestVO = new LoginRequestVO();
        LoginToken loginToken = new LoginToken();
        loginRequestVO.setLoginMobileNo(username);
        loginRequestVO.setPassword(password);
        loginRequestVO.setDeviceType(DeviceTypeEnum.H5.getDesc());
        String userRealIP = RequestUtil.getUserRealIP(httpServletRequest);
        loginRequestVO.setClientAccessIP(userRealIP);
        log.info("网贷之家登录接口###IP###mobileNo={}, ip={}", loginRequestVO.getLoginMobileNo(), userRealIP);
        log.info("登录接口,请求参数={}", JSON.toJSONString(loginRequestVO));
        if (StringUtils.isBlank(loginRequestVO.getLoginMobileNo()) || !ParameterValidator.isMobileNo(loginRequestVO.getLoginMobileNo())) {
            log.warn("登录账号需为手机号,MobileNo={}",loginRequestVO.getLoginMobileNo());
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("登录账号需为手机号");
        }
        String accounts = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.PLATEFORM_LOGIN_OPEN_ACCOUNT);
        if (accounts == null || !accounts.contains(loginRequestVO.getLoginMobileNo())){
            log.warn("登录账号不在允许的名单内,MobileNo={}",loginRequestVO.getLoginMobileNo());
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("登录账号不在允许的名单内");
        }

        UsernamePasswordDeviceToken token = new UsernamePasswordDeviceToken(loginRequestVO.getLoginMobileNo(), ParameterValidator.toTuanDaiPassword(loginRequestVO.getPassword()), DeviceTypeEnum.enumOf(loginRequestVO.getDeviceType()));
        try {
            // 登录验证
            SecurityUtils.getSubject().login(token);
        } catch (UnknownAccountException e) {
            // 账号不存在
            Exceptions.throwBizException(LoginAccountErrorCode.USERS_NOT_EXIST);
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("账号不存在");
        } catch (IncorrectCredentialsException e) {
            // 密码错误处理
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("密码错误");
        } catch (MobileUserDetailException e) {
            // 其他业务异常
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("业务异常");
        } catch (AuthenticationException e) {
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("用户登录失败");
        }catch (Exception e){
            return LoginResult.with(loginToken).setResult("-1").setErrorMsg("服务器开小差了");
        }
        String newToken = SecurityUtils.getSubject().getSession().getId().toString();
        loginToken.setToken(newToken);
        return LoginResult.with(loginToken);
    }

    @PostMapping("/getProjectsByDateForTianyan")
    @ApiOperation("网贷天眼-查询标的信息")
    public WangDaiTianYanResponseDTO getProjectsByDateForTianyan(Integer status, String time_from, String time_to,Integer page_size,Integer page_index){
        WangDaiTianYanResponseDTO responseDTO;
        try {
            responseDTO = statisticsInfoDubboService.getProjectsByDateForTianyan(this.getWangDaiTianyanRequestDto(status,time_from,time_to,page_size,page_index));
        }catch (Exception e){
            log.error("网贷天眼-查询标的信息数据异常",e);
            return this.getErrorResponseForTianyan(page_index);
        }
        return responseDTO;
    }

    @PostMapping("/getInvestorOrdersForTianyan")
    @ApiOperation("网贷天眼-查询标的投资信息")
    public WangDaiTianYanResponseDTO getInvestorOrdersForTianyan(Integer status, String time_from, String time_to,Integer page_size,Integer page_index){
        WangDaiTianYanResponseDTO responseDTO;
        try {
            responseDTO = statisticsInfoDubboService.getInvestorOrdersForTianyan(this.getWangDaiTianyanRequestDto(status,time_from,time_to,page_size,page_index));
        }catch (Exception e){
            log.error("网贷天眼-查询标的信息数据异常",e);
            return this.getErrorResponseForTianyan(page_index);
        }
        return responseDTO;
    }

    @PostMapping("/getOverdebtProjectsTianyan")
    @ApiOperation("网贷天眼-查询提前结清标的信息")
    public WangDaiTianYanResponseDTO getOverdebtProjectsTianyan(Integer status, String time_from, String time_to,Integer page_size,Integer page_index){
        WangDaiTianYanResponseDTO responseDTO;
        try {
            responseDTO = statisticsInfoDubboService.getOverdebtProjectsForTianyan(this.getWangDaiTianyanRequestDto(status,time_from,time_to,page_size,page_index));
        }catch (Exception e){
            log.error("网贷天眼-查询提前结清标的信息",e);
            return this.getErrorResponseForTianyan(page_index);
        }
        return responseDTO;
    }

    @PostMapping("/reportDataToJrb")
    @ApiOperation("深圳金融办数据上报,sign非空;reportDate可空，为空是上传前一天的数据，日期格式yyyyMMdd;reportCodes可空，为空时上传所有报表，也可以指定报表名称上传,以逗号分隔，如j1001,j1002;isAutoUpload表示是否自动报送金融办,为false时,只生成本地文件但是不上报")
    @AuthIgnore
    public Empty reportDataToJrb(String sign,String reportCodes,String reportDate_yyyyMMdd,boolean isAutoUpload){
        Assert.isTrue("niiwoo@123#reportDataToJrb".equals(sign),"签名sign不合法");
        //Assert.notNull(reportDate_yyyyMMdd,"reportDate_yyyyMMdd不可空");
        DataReportJrbRequestDTO responseDTO = new DataReportJrbRequestDTO();
        if (StringUtils.isEmpty(reportCodes)){
            responseDTO.setReportCodes(new ArrayList<>());
        }else {
            responseDTO.setReportCodes(Arrays.asList(reportCodes.split(",")));
        }
        responseDTO.setIsAutoUpload(isAutoUpload);
        responseDTO.setReportDate(reportDate_yyyyMMdd);
        try {
            statisticsInfoDubboService.reportDataToJrb(responseDTO);
        }catch (Exception e){
            log.error("金融办数据上报",e);
        }
        return Empty.getInstance();
    }

    @PostMapping("/reportDataToChinaJrb")
    @ApiOperation("中国互金金融办数据上报,sign非空;reportDate指上报日可空，为空是上传前一天的数据，日期格式yyyyMMdd")
    @AuthIgnore
    public Empty reportDataToChinaJrb(String sign,String reportDate_yyyyMMdd,boolean isAutoUpload,boolean isMonthReport,String allReportCompareDate) throws IOException {
        Assert.isTrue("niiwoo@123#reportDataToChinaJrb".equals(sign),"签名sign不合法");
        //Assert.notNull(reportDate_yyyyMMdd,"reportDate_yyyyMMdd不可空");
        DataReportChinaJrbRequestDTO requestDTO = new DataReportChinaJrbRequestDTO();

        requestDTO.setIsAutoUpload(isAutoUpload);
        requestDTO.setReportDate(reportDate_yyyyMMdd);
        requestDTO.setIsMonthReport(isMonthReport);
        requestDTO.setAllReportCompareDate(allReportCompareDate);
        try {
            statisticsInfoDubboService.reportDataToChinaJrb(requestDTO);
        }catch (Exception e){
            log.error("中国互金金融办数据上报",e);
            throw e;
        }
        return Empty.getInstance();
    }

    @PostMapping("/queryReportDataToChinaJrb")
    @ApiOperation("中国互金金融办数据上报结果")
    @AuthIgnore
    public String queryReportDataToChinaJrb(String sign,String fileName) throws IOException {
        Assert.isTrue("niiwoo@123#reportDataToChinaJrb".equals(sign),"签名sign不合法");

        String fileDir;
        try {
            fileDir = statisticsInfoDubboService.queryReportDataToChinaJrb(fileName);
        }catch (Exception e){
            log.error("中国互金金融办数据上报结果",e);
            throw e;
        }
        return fileDir;
    }

    private WangDaiTianYanRequestDTO getWangDaiTianyanRequestDto(Integer status, String time_from, String time_to,Integer page_size,Integer page_index){
        Assert.notNull(status,"参数误错");
        Assert.notNull(page_size,"参数误错");
        Assert.notNull(page_index,"参数误错");
        Date timeFrom = DateUtils.parseDateFromString(time_from,DateUtils.SHOW_DATETIME_FORMAT);
        Assert.notNull(timeFrom,"参数误错");
        Date timeTo = DateUtils.parseDateFromString(time_to,DateUtils.SHOW_DATETIME_FORMAT);
        Assert.notNull(timeTo,"参数误错");
        String openFlag = tradeConfigDubboService.selectTradeConfigByEmun(TradeConfigEnum.TIANYAN_OPEN_FLAG);
        Assert.isTrue("1".equals(openFlag),"网贷天眼数据未开放");

        WangDaiTianYanRequestDTO dto = new WangDaiTianYanRequestDTO();
        dto.setPageIndex(page_index);
        dto.setPageSize(page_size);
        dto.setStatus(status.byteValue());
        dto.setTimeFrom(timeFrom);
        dto.setTimeTo(timeTo);
        return dto;
    }

    private WangDaiTianYanResponseDTO getErrorResponseForTianyan(int page_index){
        WangDaiTianYanResponseDTO responseDTO = new WangDaiTianYanResponseDTO();
        responseDTO.setResult_msg("");
        responseDTO.setResult_code(0);
        responseDTO.setPage_index(page_index);
        responseDTO.setPage_count(0);
        responseDTO.setLoans(Collections.emptyList());
        return responseDTO;
    }

}
